<?php


namespace Packages\Sms\Services;

use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use Illuminate\Support\Facades\Cache;

class SmsService
{
    private string $accessKeyId;
    private string $accessKeySecret;
    private array $templates;

    private string $redisKey;
    private string $expire;

    public function __construct()
    {
        $this->accessKeyId = env('ALISMS_ACCESS_KEY');
        $this->accessKeySecret = env('ALISMS_ACCESS_SECRET');
        $this->templates = [
            'login' => [
                'code' => 'SMS_213425232',
                'title' => '登录异常验证码',
                'content' => '验证码${code}，您正尝试异地登录，若非本人操作，请勿泄露。',
            ],
            'register' => [
                'code' => 'SMS_213425231',
                'title' => '用户注册验证码',
                'content' => '验证码${code}，您正在注册成为新用户，感谢您的支持！',
            ],
            'update_pass' => [
                'code' => 'SMS_213425230',
                'title' => '修改密码验证码',
                'content' => '验证码${code}，您正在尝试修改登录密码，请妥善保管账户信息。',
            ],
            'update_info' => [
                'code' => 'SMS_213425229',
                'title' => '信息变更验证码',
                'content' => '验证码${code}，您正在尝试变更重要信息，请妥善保管账户信息。',
            ],
        ]; // 短信模板

        $this->redisKey = config('rediskey.userSmsCode', 'STRING:USER_SMS_CODE:PHONE:'); // 效验短信验证码redis key
        $this->expire = 60 * 15; // 效验短信验证码过期时间
    }

    /**
     * 发短信
     *
     * @param $phoneNumbers
     * @param $templateCode
     * @param $templateParam
     * @param string $regionId
     * @param string $signName
     * @return \AlibabaCloud\Client\Result\Result|string
     */
    private function sendSMS($phoneNumbers, $templateCode, $templateParam, $regionId = 'cn-hangzhou', $signName = '海南多助科技')
    {

        try {
            AlibabaCloud::accessKeyClient($this->accessKeyId, $this->accessKeySecret)
                ->regionId($regionId) // replace regionId as you need
                ->asGlobalClient();

            $result = AlibabaCloud::rpcRequest()
                //->product('Sms-intl')
                ->product('Dysmsapi')
                ->version('2017-05-25')
                ->action('SendSms')
                ->method('POST')
                ->options([
                    'query' => [
                        'RegionId' => $regionId,
                        'PhoneNumbers' => $phoneNumbers,
                        'SignName' => $signName,
                        'TemplateCode' => $templateCode,
                        'TemplateParam' => $templateParam,
                    ],
                ])
                ->request();

            app('log')->debug('sendsmd result=', $result->toArray());
            return $result;
        } catch (ClientException $e) {
            app('log')->info('client exception');
            app('log')->info($e->getErrorMessage());
            return $e->getErrorMessage() . PHP_EOL;
        } catch (ServerException $e) {
            app('log')->info('server exception');
            app('log')->info($e->getErrorMessage());
            return $e->getErrorMessage() . PHP_EOL;
        }
    }

    /**
     * 判断验证码
     *
     * @param $code
     * @param $key
     * @return array
     */
    public function checkSMS($code, $phone)
    {
        // 测试环境 默认短信验证码
        if ($code === '666666' && env('APP_ENV') != 'production') {
            return ['status' => true, 'data' => '验证码正确'];
        }

        // 获取redis中的验证码
        $value = Cache::get($this->redisKey . $phone);

        //验证码是否存在
        if (!$value) {
            return ['status' => false, 'msg' => '验证码已过期'];
        }

        //验证码是否正确
        if ($value != $code) {
            return ['status' => false, 'msg' => '验证码错误'];
        }

        return ['status' => true, 'data' => '验证码正确'];
    }

    /**
     * 发送效验短信
     *
     * @param $param
     * @return array
     */
    public function sendValidSMS($phone, $type)
    {
        // 判断短信验证码类型
        if (empty($this->templates[$type])) return ['status' => false, 'msg' => '短信验证码类型错误'];

        // 获取模板code
        $templateCode = $this->templates[$type]['code'];

        // 生成6位随机数字
        $code = $this->genRandomCode();

        // 模板参数
        $templateParam = json_encode(['code' => $code]);

        // 发送短信
        $res = $this->sendSMS($phone, $templateCode, $templateParam);

        // 将验证码存入redis
        Cache::put($this->redisKey . $phone, $code, $this->expire);

        if (@$res->toArray()['Code'] === 'OK') {
            return ['status' => true, 'data' => '短信验证码发送成功'];
        } else {
            return ['status' => false, 'msg' => '短信验证码发送失败'];
        }
    }

    /**
     * 获取6位随机数字
     *
     * @return int
     * @throws \Exception
     */
    public function genRandomCode()
    {
        $code = random_int(100000, 999999);

        return $code;
    }
}
